package com.google.code.eclipsercpspring.internal;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.springframework.beans.factory.BeanFactory;

import com.google.code.eclipsercpspring.BeanFactoryContributor;
import com.google.code.eclipsercpspring.BeanFactoryIdNotFoundException;

public class BeanFactoryRegistryImpl implements BeanFactoryRegistry {
   private Map<String, BeanFactory> factoryCache = new HashMap<String, BeanFactory>();

   public BeanFactory getBeanFactory(String factoryId) throws BeanFactoryIdNotFoundException, CoreException {
      BeanFactory beanFactory = factoryCache.get(factoryId);
      if (beanFactory == null) {
         beanFactory = lookupBeanFactory(factoryId);
         factoryCache.put(factoryId, beanFactory);
      }
      return beanFactory;
   }

   private IConfigurationElement[] getConfigurationElements() {
      IConfigurationElement[] configElements = Platform.getExtensionRegistry().getConfigurationElementsFor(
            EclipseSpringPlugin.PLUGIN_ID, EclipseSpringPlugin.EXT_BEAN_FACTORY_CONTRIBUTORS);
      return configElements;
   }

   protected BeanFactory lookupBeanFactory(String factoryId) throws BeanFactoryIdNotFoundException, CoreException {

      for (IConfigurationElement element : getConfigurationElements()) {

         String id = element.getAttribute("id");
         String parentId = element.getAttribute("parentId");

         if (id != null && factoryId.equals(id)) {
            BeanFactory parent = null;

            if (parentId != null) {
               parent = getBeanFactory(parentId);
            }

            BeanFactoryContributor contributor = (BeanFactoryContributor) element.createExecutableExtension("class");

            return contributor.contributeBeanFactory(parent);
         }

      }
      throw new BeanFactoryIdNotFoundException(factoryId);
   }
}
